﻿using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

namespace System.Xml.Serialization
{
    /// <summary>Класс методов-расширений для XML-сериализаторов</summary>
    public static class XmlSerializerExtentions
    {
        /// <summary>Объект межпоточной блокировки доступа</summary>
        private static readonly object sf_LockObject = new object();

        /// <summary>Словарь типов - сериализаторов</summary>
        private static Dictionary<Type, XmlSerializer> sf_XmlSerializersPool;

        /// <summary>Получить XML-сериализатор по указанному типу</summary>
        /// <param name="type">Тип XML-сериализатора</param>
        /// <returns>XML-сериализатор</returns>
        [DebuggerStepThrough]
        public static XmlSerializer GetSerializer(this Type type)
        {
            XmlSerializer lv_Result;
            lock(sf_LockObject)
            {
                // Если словарь отсутствует, то создать словарь
                if(sf_XmlSerializersPool == null)
                    sf_XmlSerializersPool = new Dictionary<Type, XmlSerializer>();

                //Если попытка найти в словаре экземпляр сериализатора по указанному типу не удалась
                if(!sf_XmlSerializersPool.TryGetValue(type, out lv_Result))
                    // то создать новый сериализатор
                    sf_XmlSerializersPool.Add(type, lv_Result = new XmlSerializer(type));
            }
            return lv_Result;
        }

        /// <summary>Получить XML-сериализатор по указанному типу</summary>
        /// <param name="type">Тип XML-сериализатора</param>
        /// <returns>XML-сериализатор</returns>
        [DebuggerStepThrough]
        public static XmlSerializer GetSerializer<T>()
        {
            var type = typeof(T);
            XmlSerializer lv_Result;
            lock(sf_LockObject)
            {
                // Если словарь отсутствует, то создать словарь
                if(sf_XmlSerializersPool == null)
                    sf_XmlSerializersPool = new Dictionary<Type, XmlSerializer>();

                //Если попытка найти в словаре экземпляр сериализатора по указанному типу не удалась
                if(!sf_XmlSerializersPool.TryGetValue(type, out lv_Result))
                    // то создать новый сериализатор
                    sf_XmlSerializersPool.Add(type, lv_Result = new XmlSerializer(type));
            }
            return lv_Result;
        }

        [DebuggerStepThrough]
        public static T Deserialize<T>(this Stream stream) { return (T)GetSerializer<T>().Deserialize(stream); }

        public static T Deserialize<T>(this FileInfo file)
        {
            T t;
            using(var stream = file.OpenRead())
                t = stream.Deserialize<T>();
            return t;
        }
    }
}
